package com.ht.managermentserver.security;

import com.ht.managermentserver.entity.SysUser;
import com.ht.managermentserver.sysenum.ErrorCode;
import com.ht.managermentserver.utils.JSONUtil;
import com.ht.managermentserver.utils.JsonResult;
import com.ht.managermentserver.utils.JwtTokenUtil;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author czy
 * @package com.ht.managermentserver.security
 * @date 2020/6/1 10:01
 */
public class JwtNameAndPasswordFilter extends UsernamePasswordAuthenticationFilter {

  private final ThreadLocal<Integer> rememberMe = new ThreadLocal<>();
  private final AuthenticationManager authenticationManager;

  public JwtNameAndPasswordFilter(final AuthenticationManager authenticationManager) {
    this.authenticationManager = authenticationManager;
    setFilterProcessesUrl("/api/login/login");
  }

  @Override
  public Authentication attemptAuthentication(
      final HttpServletRequest request, final HttpServletResponse response)
      throws AuthenticationException {

    try {
      // 前端传过来的是key-value数据
      final String username = request.getParameter("username");
      final String password = request.getParameter("password");

      // rememberMe.set(loginUser.getRememberMe() == null ? 0 : loginUser.getRememberMe());
      return authenticationManager.authenticate(
          new UsernamePasswordAuthenticationToken(username, password, new ArrayList<>()));
    } catch (final Exception ex) {

      return null;
    }
  }

  @Override
  protected void successfulAuthentication(
      final HttpServletRequest request,
      final HttpServletResponse response,
      final FilterChain chain,
      final Authentication authResult)
      throws IOException, ServletException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/json;charset=utf-8");
    final JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
    System.out.println("jwtUser:" + jwtUser.toString());
    // final boolean isRemember = rememberMe.get() == 1;

    String role = "";
    final Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
    for (final GrantedAuthority authority : authorities) {
      role = authority.getAuthority();
    }

    final SysUser sysUser = new SysUser();

    sysUser.setUserName(jwtUser.getUsername());
    sysUser.setId(jwtUser.getId());
    sysUser.setPassWord(jwtUser.getPassword());

    final String token = JwtTokenUtil.createJwtToken(sysUser);
    // String token = JwtTokenUtils.createToken(jwtUser.getUsername(), false);
    // 返回创建成功的token
    // 但是这里创建的token只是单纯的token
    // 按照jwt的规定，最后请求的时候应该是 `Bearer token`
    response.setHeader(JwtTokenUtil.TOKEN_HEADER, token);
    final Map<String, Object> result = new HashMap<>(2);
    result.put("authorization", token);
    result.put("user", sysUser);
    response
        .getWriter()
        .write(JSONUtil.toJsonString(JsonResult.create("登录成功", ErrorCode.SUCCESS, result)));
  }

  @Override
  protected void unsuccessfulAuthentication(
      final HttpServletRequest request,
      final HttpServletResponse response,
      final AuthenticationException failed)
      throws IOException, ServletException {
    try {
      response.setCharacterEncoding("UTF-8");
      response.setContentType("text/json;charset=utf-8");
      response
          .getWriter()
          .write(
              JSONUtil.toJsonString(
                  JsonResult.create("认证失败", ErrorCode.ERROR, failed.getMessage())));
    } catch (final IOException e) {
      e.printStackTrace();
    }
  }
}
